package com.fofo.test.caculator.ctrl;

import com.fofo.test.caculator.common.StackArray;
import com.fofo.test.caculator.constant.ExpressionEnum;

public class Caculator {

    private StackArray numberStack = new StackArray(10);//表达式数字
    private StackArray operatorStack = new StackArray(5);//表达式运算符
    private StackArray expressionStack = new StackArray(15);//表达式
    private String undoExpression = null;//撤销暂存值

    /**
     * 运算
     * @param number1
     * @param number2
     * @param operator
     * @return
     */
    public int caculate (int number1, int number2, String operator){
        int result = 0;
        switch (operator){
            case "*":
                result = number1 * number2;
                break;
            case "/":
                result = number2 / number1;
                break;
            case "+":
                result = number1 + number2;
                break;
            case "-":
                result = number2 - number1;
                break;
        }
        return result;
    }

    /**
     * 获取输入字符类型
     * @param str
     * @return
     */
    private ExpressionEnum getExpresssionType(String str){

        if (str != null){
            if(str.equals("+") || str.equals("-") ){
                return ExpressionEnum.OPER_ADD_SUBTRACT;
            }else if (str.equals("*") || str.equals("/")){
                return ExpressionEnum.OPER_MULTIPLY_DIVIDE;
            }else if (str.equals(">") ){
                return ExpressionEnum.REDO;
            }else if (str.equals("<") ){
                return ExpressionEnum.UNDO;
            }
        }
        return ExpressionEnum.NUMBER;
    }

    private int strToInt(String number){
        return Integer.parseInt(String.valueOf(number));
    }

    /**
     * 操作表达式字符
     * @param expression
     */
    public void operation(String expression) {
        if (undoExpression != null) {
//            System.out.println("cancel undo:"+undoExpression);
            undoExpression = null;//输入后撤销undo
        }
        expressionStack.push(expression);

        if (getExpresssionType(expression) == ExpressionEnum.NUMBER) {
            if (!numberStack.full()) {
                numberStack.push(expression);
            }
        } else {
            if ( !operatorStack.empty() ) {
                if( getExpresssionType(operatorStack.getStackTop()) == ExpressionEnum.OPER_MULTIPLY_DIVIDE) {//判断当前栈内的操作符"*","/"，运算后压入栈
                    int number = caculate(strToInt(numberStack.pop()), strToInt(numberStack.pop()), operatorStack.pop());
                    numberStack.push(number + "");
                }
            }
            operatorStack.push(expression);
        }
    }

    /**
     * 撤销操作
     */
    public void undo(){
        if (undoExpression == null) {//存在undo无法继续向上undo
            undoExpression = expressionStack.pop();
            if (getExpresssionType(undoExpression) == ExpressionEnum.NUMBER) {
                numberStack.pop();
            } else {
                operatorStack.pop();
            }
        }
    }

    /**
     * 重做操作
     */
    public void redo() {
        if (undoExpression != null & !undoExpression.equals("")) {
            operation(undoExpression);
        }
    }

    /**
     * 获取表达式结果
     * @return
     */
    public int getResult(){
        int result = 0;
        while (!operatorStack.empty()){
            result = caculate(strToInt(numberStack.pop()), strToInt(numberStack.pop()), operatorStack.pop());
            numberStack.push(result+"");
        }
        return result;
    }

    public static void main(String[] args) {

        Caculator c = new Caculator();

        c.operation("16");
        c.operation("+");
        c.operation("8");
        c.operation("-");
        c.undo();//运算符undo
        c.operation("/");
        c.operation("4");
        c.undo();//数字undo
        c.redo();
        c.operation("*");
        c.operation("2");
        c.operation("-");
        c.operation("9");

        c.expressionStack.printArray();
        System.out.print("=" + c.getResult());
    }

}
